package com.user.controller.Token;

import DTO.EditPasswordDTO;
import VO.EditUserMsgVO;
import VO.UserMsgVO;
import com.user.service.UserService;
import com.utils.Sample;
import constant.CodeConstant;
import constant.MsgConstant;
import constant.RedisPreKeyConstant;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.apache.bcel.classfile.Code;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import result.Result;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.utils.ImageUtils.isSafeImageFile;
import static com.utils.ImageUtils.saveMultipartFile;
import static com.utils.PasswordUtil.isValidPassword;
import static com.utils.Sample.generateFourDigitVerificationCode;
import static com.utils.Sample.sendSms;

/**
 * 用户信息控制类
 */
@RestController
@RequestMapping("/user")
@Slf4j
public class UserMsgController {

    @Value("${ying_yan.avatar_path}")
    private String avatar_path;

    @Autowired
    private UserService userService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 用户上传头像
     * header 中 required = false 用于表示userId不必要
     * @param image 头像图片
     * @return 51 图片格式不正确
     */
    @PostMapping("/uploadAvatar")
    public Result<String> uploadImage(@RequestHeader(name = "userId") String userId,
                                      @RequestParam("image") MultipartFile image) {

        // 1. 先对这个图片文件进行安全校验
        if (!isSafeImageFile(image)){
            // 表示这个文件可能不是图片文件或者这个文件不安全
            return Result.error(MsgConstant.IMAGE_FORMAT_NOT_RIGHT, CodeConstant.IMAGE_FORMAT_NOT_RIGHT);
        }

        // 3. 拼装文件头像名 avatar_+userId
        String newFileName = "avatar_" + userId;

        // 4. 保存文件
        if (!saveMultipartFile(image,avatar_path,newFileName)){
            return Result.error(MsgConstant.NETWORK_ERROR,CodeConstant.NETWORK_ERROR);
        }

        // 5. 保存文件地址
        String path = avatar_path + File.separator + newFileName + Objects.requireNonNull(image.getOriginalFilename()).substring(image.getOriginalFilename().lastIndexOf('.'));
        userService.saveAvatar(path, Integer.valueOf(userId));

        return Result.success();
    }

    /**
     * 获取用户头像
     * @param userId 头信息 用户id
     * @return 用户头像
     */
    @GetMapping(value = "/getAvatar", produces = MediaType.IMAGE_JPEG_VALUE)
    public ResponseEntity<Resource> getImage(@RequestHeader(name = "userId") String userId) {
        try {
            Path path = Paths.get(userService.getAvatar(userId)).toAbsolutePath();
            Resource resource = new UrlResource(path.toUri());

            if (resource.exists() || resource.isReadable()) {
                return ResponseEntity.ok()
                        .contentType(MediaType.IMAGE_JPEG)
                        .body(resource);
            } else {
                // 资源不存在或不可读，返回404
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            // 处理异常，返回500或其他状态码
            return ResponseEntity.notFound().build();
        }
    }


    /**
     * 获取用户信息
     * @param userId 用户id
     * @return 用户信息
     */
    @GetMapping("/getUserMsg")
    public Result<UserMsgVO> getUserMsg(@RequestHeader(name = "userId") String userId){
        return Result.success(userService.getUserMsg(userId));
    }


    /**
     * 用户修改自己的个人信息
     * 用户昵称最长为10位
     * @return 成功标识
     * 103 参数不满足要求 性别不为0或者1,或者用户长度超过10位
     */
    @PutMapping("/editUserMsg")
    public Result<String> editUserMsg(@RequestHeader(name = "userId") String userId, @RequestBody EditUserMsgVO editUserMsgVO){
        // 先判断这个参数是否符合要求
        if (editUserMsgVO.getSex() !=0 && editUserMsgVO.getSex() != 1){
            // 表示性别发送错误
            return Result.error(MsgConstant.USER_SET_ONLY_0_AND_1,CodeConstant.PARAM_NOT_SATISFY);
        }

        if (editUserMsgVO.getUserName().length()>10){
            // 用户昵称最长位10位字符
            return Result.error(MsgConstant.USERNAME_OVER_TEN,CodeConstant.PARAM_NOT_SATISFY);
        }

        userService.editUserMsg(userId,editUserMsgVO);
        return Result.success();
    }


    /**
     * 判断用户有无设置密码
     * @param userId 用户id
     * @return 0表示没有设置密码
     * 1表示设置过密码
     */
    @GetMapping("/getPasswordType")
    public Result<Integer> getPasswordType(@RequestHeader(name = "userId") String userId){
        return Result.success(userService.getPasswordType(Integer.valueOf(userId)));
    }

    /**
     * 新用户在设置密码的时候获取验证码
     * @param phoneNumber 用户手机号，用于验证
     * @return code=200
     * 103 参数不正确，手机号不正确
     * 10 重复获取验证码
     * 500 发送短信时发生错误
     */
    @GetMapping("/getCodeByEditPassword/{phoneNumber}")
    public Result<String> getCodeByEditPassword(@RequestHeader(name = "userId") String userId,
                                                @PathVariable String phoneNumber){
        // 1. 判断手机号是否正确
        String userPhoneNumber = userService.getUserPhone(Integer.valueOf(userId));
        if (!Objects.equals(userPhoneNumber, phoneNumber)){
            return Result.error(MsgConstant.PARAM_NOT_SATISFY,CodeConstant.PARAM_NOT_SATISFY);
        }

        String key = RedisPreKeyConstant.USER_SET_PASSWORD + phoneNumber;

        // 2. 判断是否重复发送验证码
        String RedisCode = stringRedisTemplate.opsForValue().get(key);
        if (RedisCode!=null){
            // 表示验证码未失效
            return Result.error(MsgConstant.REPEATEDLY_GET_CODE,CodeConstant.REPEATEDLY_GET_CODE);
        }

        // 3. 生成验证码并将这个验证码保存到redis中3分钟
        String code = generateFourDigitVerificationCode();

        // 将用户验证码保存到redis中
        stringRedisTemplate.opsForValue().set(key,code,180L, TimeUnit.SECONDS);

        // 4. 发生验证码
        try {
            sendSms(phoneNumber,code);
        } catch (Exception e) {
            log.error("发送短信时发送错误");
            return Result.error(MsgConstant.NETWORK_ERROR,CodeConstant.NETWORK_ERROR);
        }

        return Result.success();
    }


    /**
     * 用户修改密码
     *  type ： 0表示设置密码 1表示修改密码
     * @param editPasswordDTO 用户的密码
     * @return 提示
     * 103 参数不满足要求 type既不是0也不是1
     * 101 缺少必要的参数
     * 11 验证码已经过期了
     * 12 验证码不正确
     * 13 密码不正确
     * 106 密码不符合标准
     * 500 表示用户有密码，还要进行设置密码
     */
    @PostMapping("/editPassword")
    public Result<String> EditPassword(@RequestHeader(name = "userId") String userId,
                                       @RequestBody EditPasswordDTO editPasswordDTO){
        // 1. 判断是那种类型
        if (editPasswordDTO.getType()==0){
            // 1.1 设置密码
            // 1.2 获取redis中的验证码
            String key = RedisPreKeyConstant.USER_SET_PASSWORD+userService.getUserPhone(Integer.valueOf(userId));
            String code = stringRedisTemplate.opsForValue().get(key);

            if (code==null){
                // 1.2.1 验证码已经过期
                return Result.error(MsgConstant.CODE_EXPIRATION,CodeConstant.CODE_EXPIRATION);
            }

            if (!code.equals(editPasswordDTO.getCode())){
                // 1.2.2 验证码不正确
                return Result.error(MsgConstant.CODE_NOT_RIGHT,CodeConstant.CODE_NOT_RIGHT);
            }

            // 1.3 表示验证码正确,进行密码规格验证
            if (!isValidPassword(editPasswordDTO.getNewPassword())){
                // 密码标准不通过
                return Result.error(MsgConstant.PASSWORD_IS_SATISFY,CodeConstant.PASSWORD_IS_SATISFY);
            }

            // 1.4 将密码交给service进行保存
            userService.savePassword(editPasswordDTO.getNewPassword(),Integer.valueOf(userId));

            return Result.success();
        }else if (editPasswordDTO.getType()==1){
            // 1.2 修改密码

            // 1.2.1 判断有无数据
            if (editPasswordDTO.getNewPassword()==null||
                    editPasswordDTO.getNewPassword().isEmpty() ||
                    editPasswordDTO.getOldPassword() == null||
                    editPasswordDTO.getOldPassword().isEmpty()
            ){
                return Result.error(MsgConstant.LACK_PARAM,CodeConstant.LACK_PARAM);
            }
            // 判断新密码规格
            if (!isValidPassword(editPasswordDTO.getNewPassword())){
                // 密码标准不通过
                return Result.error(MsgConstant.PASSWORD_IS_SATISFY,CodeConstant.PASSWORD_IS_SATISFY);
            }
            userService.updatePassword(editPasswordDTO,Integer.valueOf(userId));
            return Result.success();
        }
        // 1.3 type 不满足要求
        return Result.error(MsgConstant.PARAM_NOT_SATISFY,CodeConstant.PARAM_NOT_SATISFY);
    }
}
